package com.yunbiao.ybbusstopplate.serialport.agreement;

import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.google.gson.reflect.TypeToken;
import com.yunbiao.ybbusstopplate.bean.SiteInfoBean;
import com.yunbiao.ybbusstopplate.utils.BytesUtils;
import com.yunbiao.ybbusstopplate.utils.StringUtils;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;

/***通信包结构
 * 开始符        1     (0x7E)标识通信包的开始                                      0
 * 目标地址      1     通信接收方地址                                              1
 * 源地址        1     通信放发起地址                                              2
 * 消息帧类型     1     消息帧的标识                                               3
 * 流水号        1     包流水号，发起方填写流水号，接收方回复消息时将此流水号回 发。     4
 * 消息帧长度     2     消息帧长度，从数据帧 1 开始累加到校验位的前一个字节。           5\6
 * 数据帧1标识    1     数据帧 1 的唯一标识。                                       7
 * 数据帧1长度    2     数据帧 1 数据内容的长度。                                   8\9
 * 数据帧1内容    N     数据帧 1 的数据内容。                                       8
 * 数据帧n标识    1     数据帧 n 的唯一标识。                                       9
 * 数据帧n长度    2     数据帧 n 数据内容的长度。                                   10
 * 数据帧n内容    N     数据帧 n 的数据内容。                                       11
 * 校验位         1     从包头标识到校验位前的所有字节的异或值                        12
 * 结束符         1     (0x7F)标识通信包的结束                                     13
 */

/***设备地址定义
 * 车载终端主机 0x01
 * 手动报站器 0x02
 * 车载硬盘录像机 0x03
 * 预留 0x04-0x0F
 * 车内报站显示屏 0x10-0x1F
 * 站节牌 0x20-0x2F
 * 路牌 0x30-0x3F
 * 媒体播放机 0x40-0x4F
 * 电子收费器（IC卡机） 0x50-0x5F
 * 空调 0x60
 * 温度采集器 0x70-0x7F
 * 行车安全记录仪 0x80
 * 考勤机 0x81
 * 投币机 0x82
 * 油量采集器 0x83
 * 预留 0x84-0x8F
 * 广告牌 0x90-0x93
 * 客流检测仪 0xA0-0xAF
 * 广播地址 0xFF
 */
public class HXPortAgreement extends BaseAgreement{
    private static final String TAG = "HXPortAgreement";

    private String lineName = "";
    private String upDown = "00";
    private final LinkedHashMap<Integer,String> upMap = new LinkedHashMap<>();
    private final LinkedHashMap<Integer,String> downMap = new LinkedHashMap<>();
    private final File upMapFile = new File(Environment.getExternalStorageDirectory(),"upMap.txt");
    private final File downMapFile = new File(Environment.getExternalStorageDirectory(),"downMap.txt");
    private final File lineNameFile = new File(Environment.getExternalStorageDirectory(),"lineName.txt");
    private final File upDownFile = new File(Environment.getExternalStorageDirectory(),"upDown.txt");

    private static HXPortAgreement hxPortAgreement;
    private final AgreementDataTool dataTool;

    private HXPortAgreement(){
        dataTool = new AgreementDataTool();
        dataTool.setSHex("7e");
        dataTool.setEHex("7f");
        dataTool.setDataReceive(new AgreementDataTool.AgreementDataReceive() {
            @Override
            public void onDataReceive(byte[] datas) {
                if(datas.length == 0){
                    return;
                }
//                choiceData(datas);
                handleData(datas);
            }
        });

        ThreadUtils.executeBySingle(new ThreadUtils.SimpleTask<Object>() {
            @Override
            public Object doInBackground() throws Throwable {
                upMap.putAll(readFileToMap(upMapFile));
                downMap.putAll(readFileToMap(downMapFile));
                lineName = readFileToString(lineNameFile);
                String s = readFileToString(upDownFile);
                upDown = TextUtils.isEmpty(s) ? "00" : s;
                return new Object();
            }

            @Override
            public void onSuccess(Object o) {

            }
        });
    }

    public static synchronized HXPortAgreement getInstance(){
        if(hxPortAgreement == null){
            hxPortAgreement = new HXPortAgreement();
        }
        return hxPortAgreement;
    }

    public synchronized void anlzData(byte[] datas){
        dataTool.handleData(datas);
    }

    private ByteBuffer msgBuffer;
    private void handleData(byte[] bytes){
        if(msgBuffer != null){
            msgBuffer.clear();
            msgBuffer = null;
        }

        if(bytes == null || bytes.length == 0){
            return;
        }

        msgBuffer = ByteBuffer.wrap(bytes);

        byte startB = msgBuffer.get();//0
        byte destDeviceB = msgBuffer.get();//1目标设备类型
        if(destDeviceB == (byte) 0xff){
            return;
        }

        byte originDeviceB = msgBuffer.get();//2
        byte msgFlagB = msgBuffer.get();//3消息帧类型
        byte msgSerialB = msgBuffer.get();//4流水号
        //消息帧长度
        byte[] msgLengthBs = new byte[2];
        msgBuffer.get(msgLengthBs);//5、6消息帧长度
        int msgLength = BytesUtils.hex16to10(BytesUtils.bytesToHex(msgLengthBs));
        //消息帧数据
        byte[] msgData = new byte[msgLength];
        msgBuffer.get(msgData);
        ByteBuffer msgDataBuffer = ByteBuffer.wrap(msgData);
        try {
            switch (msgFlagB) {
                case (byte)0x03:
                    inOutBroadSite(msgDataBuffer);
                    break;
                case (byte)0x04:
                    getLineInfo(msgDataBuffer);
                    break;
                case (byte)0x10:
                    resolveSiteList(msgDataBuffer);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getLineInfo(ByteBuffer msgDataBuffer){
        Map<Byte,String> dataFrameMap = new HashMap<>();
        while (msgDataBuffer.hasRemaining()) {
            //数据帧类型
            byte dataType = msgDataBuffer.get();

            //数据帧长度
            byte[] dataLengthBs = new byte[2];
            msgDataBuffer.get(dataLengthBs);//8、9
            int dataLength = BytesUtils.hex16to10(BytesUtils.bytesToHex(dataLengthBs));

            //数据帧
            byte[] dataBs = new byte[dataLength];
            msgDataBuffer.get(dataBs);

            switch (dataType) {
                case (byte) 0x30://路牌图片显示命令

                    break;
                case (byte) 0x31://线路名称标识
                case (byte) 0x32://始发站中文名称标识
                case (byte) 0x33://始发站备用名称标识
                case (byte) 0x34://终点站中文名称标识
                case (byte) 0x35://终点站备用名称标识
                    String dataString = StringUtils.hexStringToString(BytesUtils.bytesToHex(dataBs));
                    e("取数据：" + dataString);
                    dataFrameMap.put(dataType,dataString);
                    break;
                case (byte) 0x97://指定显示位置

                    break;
                case (byte) 0x02://上行下行标识
                case (byte) 0xB9://线路类型
                    dataFrameMap.put(dataType,BytesUtils.bytesToHex(dataBs));
                    break;
                default:
                    break;
            }
        }

        String lineName = dataFrameMap.get((byte) 0x31);//线路名
        String startSiteName = dataFrameMap.get((byte) 0x32);//始发站名
        String endSiteName = dataFrameMap.get((byte) 0x34);//终点站名
        String upDown = dataFrameMap.get((byte) 0x02);//终点站名
        String lineType = dataFrameMap.get((byte) 0xB9);//终点站名

        if(lineName != null && !TextUtils.isEmpty(lineName) && lineName.contains("路")){
            lineName = lineName.replaceAll("路","");
        }

        Log.d(TAG, "车次：" + lineName +
                "---> 始发站：" + startSiteName +
                "---> 终点站：" + endSiteName +
                "---> 上下行：" + upDown +
                "---> 线路类型：" + lineType
        );

        if(!TextUtils.isEmpty(lineName)){
            writeStringToFile(lineNameFile,lineName);
            this.lineName = lineName;
        }
        if(agreementListener != null){
            agreementListener.onLineInfoResult(new String[]{lineName, startSiteName, endSiteName});
        }

        if(upDown != null && !TextUtils.isEmpty(upDown)){
            writeStringToFile(upDownFile,upDown);
            if(!TextUtils.equals(this.upDown,upDown)){
                this.upDown = upDown;
                if(TextUtils.equals("01",this.upDown)){
                    Log.d(TAG, "11111: 发送上行站点");
                    if(agreementListener != null){
                        agreementListener.onSiteListResult(new ArrayList<>(upMap.values()));
                    }
                } else if(TextUtils.equals("02",this.upDown)){
                    Log.d(TAG, "11111: 发送下行站点");
                    if(agreementListener != null){
                        agreementListener.onSiteListResult(new ArrayList<>(downMap.values()));
                    }
                }
            }
        }

    }

    private void inOutBroadSite(ByteBuffer msgDataBuffer){
        Map<Byte,Integer> dataFrameMap = new HashMap<>();
        while (msgDataBuffer.hasRemaining()) {
            //数据帧类型
            byte dataType = msgDataBuffer.get();

            //数据帧长度
            byte[] dataLengthBs = new byte[2];
            msgDataBuffer.get(dataLengthBs);//8、9
            int dataLength = BytesUtils.hex16to10(BytesUtils.bytesToHex(dataLengthBs));

            //数据帧
            byte[] dataBs = new byte[dataLength];
            msgDataBuffer.get(dataBs);

            switch (dataType) {
                case (byte) 0x02:
                case (byte) 0x03:
                case (byte) 0x04:
                case (byte) 0x05:
                    int dataInt = BytesUtils.hex16to10(BytesUtils.bytesToHex(dataBs));
                    e("取数据：" + dataInt);
                    dataFrameMap.put(dataType,dataInt);
                    break;
            }
        }

        Integer upDownFlag = dataFrameMap.get((byte) 0x02);
        Integer siteTypeFlag = dataFrameMap.get((byte) 0x03);
        Integer inOutFlag = dataFrameMap.get((byte) 0x04);
        Integer siteNumber = dataFrameMap.get((byte) 0x05);
        if(upDownFlag == null || inOutFlag == null || siteNumber == null){
            return;
        }
        Log.d(TAG, "上下行标识：" + upDownFlag + " ,站点类型标识：" + siteTypeFlag + " ,进出站标识：" + inOutFlag + " ,站点序号：" + siteNumber);

        String upDown = "0" + upDownFlag;
        if(!TextUtils.equals(upDown,this.upDown)){
            this.upDown = upDown;
            if(TextUtils.equals("01",this.upDown)){
                Log.d(TAG, "22222: 发送上行站点");
                if(agreementListener != null){
                    agreementListener.onSiteListResult(new ArrayList<>(upMap.values()));
                }
            } else if(TextUtils.equals("02",this.upDown)){
                Log.d(TAG, "22222: 发送下行站点");
                if(agreementListener != null){
                    agreementListener.onSiteListResult(new ArrayList<>(downMap.values()));
                }
            }
        }

        Iterator<Map.Entry<Integer, String>> iterator = null;
        String siteName = "";
        if(upDownFlag == 1){
            siteName = upMap.get(siteNumber);
            iterator = upMap.entrySet().iterator();
        } else if(upDownFlag == 2){
            siteName = downMap.get(siteNumber);
            iterator = downMap.entrySet().iterator();
        }

        int index = -1;
        if(iterator != null){
            while (iterator.hasNext()) {
                index ++;
                Map.Entry<Integer, String> next = iterator.next();
                if(Objects.equals(next.getKey(), siteNumber)){
                    break;
                }
            }
        }

        SiteInfoBean siteInfoBean = new SiteInfoBean();
        siteInfoBean.setSiteName(siteName);
        siteInfoBean.setStutas(inOutFlag == 1 ? 1 : 0);
        siteInfoBean.setIndex(index);

        if(agreementListener != null){
            agreementListener.onSiteTipResult(siteInfoBean);
        }
    }

    private void resolveSiteList(ByteBuffer msgDataBuffer){
        while (msgDataBuffer.hasRemaining()) {
            //数据帧类型
            byte dataType = msgDataBuffer.get();
            //数据帧长度
            byte[] dataLengthBs = new byte[2];
            msgDataBuffer.get(dataLengthBs);//8、9
            int dataLength = BytesUtils.hex16to10(BytesUtils.bytesToHex(dataLengthBs));

            //数据帧
            byte[] dataBs = new byte[dataLength];
            msgDataBuffer.get(dataBs);
            ByteBuffer dataBuffer = ByteBuffer.wrap(dataBs);

            switch (dataType) {
                case (byte)0x21:{
                    deleteFile(upMapFile);
                    upMap.clear();
                    LinkedHashMap<Integer, String> siteMap = getSiteList(dataBuffer);
                    upMap.putAll(siteMap);
                    writeMapToFile(upMapFile,upMap);
                    d("getSiteList: " + upMap.toString());
                    if(agreementListener != null && TextUtils.equals("01",this.upDown)){
                        Log.d(TAG, "33333: 发送上行站点");
                        agreementListener.onSiteListResult(new ArrayList<>(upMap.values()));
                    }
                    break;
                }
                case (byte)0x22:{
                    deleteFile(downMapFile);
                    downMap.clear();
                    LinkedHashMap<Integer, String> siteMap = getSiteList(dataBuffer);
                    downMap.putAll(siteMap);
                    writeMapToFile(downMapFile,downMap);
                    d("getSiteList: " + downMap.toString());
                    if(agreementListener != null && TextUtils.equals("02",this.upDown)){
                        Log.d(TAG, "33333: 发送下行站点");
                        agreementListener.onSiteListResult(new ArrayList<>(downMap.values()));
                    }
                    break;
                }
            }
        }
    }

    private LinkedHashMap<Integer,String> getSiteList(ByteBuffer dataBuffer){
        byte[] array = dataBuffer.array();
        String s = BytesUtils.bytesToHex(array);
        Log.d(TAG, "getSiteList: " + s);

        LinkedHashMap<Integer,String> siteMap = new LinkedHashMap<>();
        while (dataBuffer.hasRemaining()) {
            String s1 = BytesUtils.byteToHex(dataBuffer.get());
            int index = BytesUtils.hex16to10(s1);
            d("序号：" + index + " --- " + s1);

            String s2 = BytesUtils.byteToHex(dataBuffer.get());
            int chLength = BytesUtils.hex16to10(s2);
            d("中文名长度：" + chLength + " --- " + s2);
            if(chLength > 0){
                byte[] bytes = new byte[chLength];
                dataBuffer.get(bytes);
                String s3 = BytesUtils.bytesToHex(bytes);
                String chName = StringUtils.hexStringToString(s3);
                d("中文名：" + chName + " --- " + s3);
                siteMap.put(index,chName);
            }

            String s4 = BytesUtils.byteToHex(dataBuffer.get());
            int enLength = BytesUtils.hex16to10(s4);
            d("英文名长度：" + enLength + " --- " + s4);
            if (enLength > 0) {
                byte[] bytes = new byte[enLength];
                dataBuffer.get(bytes);
                String s5 = BytesUtils.bytesToHex(bytes);
                String enName = StringUtils.hexStringToString(s5);
                d("英文名：" + enName + " --- " + s5);
            }
        }
        return siteMap;
    }

    private void deleteFile(File file){
        if (FileUtils.isFileExists(file)) {
            boolean delete = FileUtils.delete(file);
            Log.d(TAG, "删除：" + file.getName() + "--->" + delete);
        }
    }

    private String readFileToString(File file){
        String string = "";
        if(FileUtils.isFileExists(file) && FileUtils.isFile(file)){
            String string1 = FileIOUtils.readFile2String(file);
            if(!TextUtils.isEmpty(string1)){
                string = string1;
            }
        }
        return string;
    }

    private void writeStringToFile(File file,String string){
        if(!TextUtils.isEmpty(string)){
            boolean b = FileIOUtils.writeFileFromString(file, string, false);
            Log.d(TAG, "写出："+ file.getName() + "--->" + b);
        } else {
            Log.d(TAG, "写出内容为空");
        }
    }

    private void writeMapToFile(File file,LinkedHashMap<Integer,String> map){
        String s = GsonUtils.toJson(map);
        Log.d(TAG, "writeMapToFile: " + s);
        writeStringToFile(file,s);
    }

    private LinkedHashMap<Integer,String> readFileToMap(File file){
        String s = readFileToString(file);
        if(!TextUtils.isEmpty(s)){
            return GsonUtils.fromJson(s,new TypeToken<LinkedHashMap<Integer,String>>(){}.getType());
        }
        return new LinkedHashMap<>();
    }

    private void d(String log){
        Log.d(TAG, log);
    }

    private void e(String log){
        Log.e(TAG, log);
    }

    public void test(){
        File file = new File(Environment.getExternalStorageDirectory(),"666666.txt");
        List<String> strings = FileIOUtils.readFile2List(file);
        Log.d(TAG, "test: " + strings.size());
        for (String string : strings) {
            if(string.contains("<---")){
                String[] split = string.split("<---");
                String s = split[1].trim().replaceAll(" ","");
                Log.d(TAG, "test: " + s);
                byte[] bytes = BytesUtils.hexToByteArray(s);
                anlzData(bytes);
            }
        }
    }
}
